package com.baiyun.yunpan.Util;


import com.baiyun.yunpan.entity.FilesDetail;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import io.minio.messages.Upload;
import io.minio.policy.PolicyType;
import org.xmlpull.v1.XmlPullParserException;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;


public class MinioUtils {

    private  static String minioUrl="http://103.39.222.103:9000/";
    private  static String minioUser="minioadmin";
    private  static String minioPaw="minioadmin";

    private static MinioClient minioClient;
    private static MinioUtils minioUtils;

    private MinioUtils() throws InvalidPortException, InvalidEndpointException {
        minioClient=new MinioClient(minioUrl, minioUser, minioPaw);
    }
    public static MinioUtils getMinio() throws InvalidPortException, InvalidEndpointException{
        if(minioClient==null){
            minioUtils=new MinioUtils();
            return minioUtils;
        }else {
            return minioUtils;
        }

    }

    /***
     * 上传文件的方法
     * @param PathName
     * @param fileStream
     * @param bucketName
     * @param contentType
     * @return
     * @throws IOException
     */
    public  String  objectUpload(String PathName, InputStream fileStream, String bucketName,String contentType) throws IOException {

        try {
            minioClient.putObject(bucketName, PathName, fileStream,contentType);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


    /***
     * 获取首页的文件夹
     * @return
     * @throws Exception
     */

    public  List<FilesDetail> getIndexFolders() throws Exception{

        List<FilesDetail> filesDetails=new ArrayList<>();
        List<Bucket> buckets = minioClient.listBuckets();
        buckets.forEach(e->{
            FilesDetail filesDetail = new FilesDetail();
            String indexFolder=e.name();
            filesDetail.setFileName(indexFolder);
            filesDetail.setFileSize(0);
            filesDetail.setFileLastTime("-");
            filesDetail.setFileType("folder");
            filesDetails.add(filesDetail);
        });
            return filesDetails;
    }


    /***
     * 获取文件的url
     * @param bucketName
     * @param objectName
     * @return
     * @throws Exception
     */
    public String getObjectUrl(String bucketName,String objectName) throws Exception{
       return minioClient.getObjectUrl(bucketName, objectName);
    }

    /**
     * 创建文件夹 并赋予读取权限
     * @param bucketName
     * @throws Exception
     */
    public void makeBecket(String bucketName)throws  Exception{
        minioClient.makeBucket(bucketName);
        minioClient.setBucketPolicy(bucketName, "*",PolicyType.READ_ONLY);
    }

    /***
     * 获取不同路径下的文件
     * @param bucketName
     * @param prefix
     * @return
     * @throws Exception
     */
    public  List<FilesDetail> getObjects(String bucketName,String prefix) throws Exception{

        Iterable<Result<Item>> face = minioClient.listObjects(bucketName,prefix);
        List<FilesDetail> filesDetails=new ArrayList<>();
        //                存放文件夹名称的数组
        List<String> paths=new ArrayList<>();
        face.forEach(e->{
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Item item = e.get();
                String objectName = item.objectName();

                //        如果有前缀 则要进行处理
                //        比如 test/ces/1.png 前缀是test 则要把 test/去掉
                if(prefix!=null){
                    int index = prefix.length();
                    objectName = objectName.substring(index, objectName.length());
                }

                //                获取到文件路径  判断文件路径是否包含/ 包含/则代表存在文件夹
                //                是文件夹则进行处理
                if(objectName.indexOf("/")>0){
                    getFolder(objectName,paths);
                }else {
                    FilesDetail filesDetail = new FilesDetail();
                    filesDetail.setFileName(objectName);
                    filesDetail.setFileLastTime(sdf.format(item.lastModified()));
                    filesDetail.setFileSize(item.objectSize()/1024);
                    filesDetail.setFileType(getFileLastName(objectName));
                    filesDetails.add(filesDetail);
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }

        });
//        普通文件处理完毕 需要对文件夹处理
        paths.forEach(e->{
            FilesDetail filesDetail = new FilesDetail();
            filesDetail.setFileName(e);
            filesDetail.setFileType("folder");
            filesDetail.setFileSize(0);
            filesDetails.add(filesDetail);
        });

        return filesDetails;
    }


    public  List<FilesDetail> getAllObjects(String bucketName) throws Exception{

        Iterable<Result<Item>> face = minioClient.listObjects(bucketName);
        List<FilesDetail> filesDetails=new ArrayList<>();
        //                存放文件夹名称的数组
        List<String> paths=new LinkedList<>();
        face.forEach(e->{
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Item item = e.get();
                String objectName = item.objectName();
                //                获取到文件路径  判断文件路径是否包含/ 包含/则代表存在文件夹
                //                是文件夹则进行处理
                if(objectName.indexOf("/")>0){
                    int i = objectName.lastIndexOf("/");
                    FilesDetail filesDetail = new FilesDetail();
                    filesDetail.setFileName(objectName.substring(i+1));
                    filesDetail.setFileLastTime(sdf.format(item.lastModified()));
                    filesDetail.setFileSize(item.objectSize()/1024);
                    filesDetail.setFileType(getFileLastName(objectName));
                    filesDetails.add(filesDetail);

                }else {
                    FilesDetail filesDetail = new FilesDetail();
                    filesDetail.setFileName(objectName);
                    filesDetail.setFileLastTime(sdf.format(item.lastModified()));
                    filesDetail.setFileSize(item.objectSize()/1024);
                    filesDetail.setFileType(getFileLastName(objectName));
                    filesDetails.add(filesDetail);
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }

        });
        return filesDetails;
    }

    /***
     * 删除文件夹或文件的方法
     */
    public void deleteObjetc(String bucketName,String objectName) throws Exception{
        minioClient.removeObject(bucketName, objectName);

    }

    /**
     * 删除bucket的方法
     */
    public void deleteBucket(String bucketName) throws Exception{
        minioClient.removeBucket(bucketName);
    }


    /***
     * 获取文件名
     * @param fileName
     * @return
     */
    public String getFileLastName(String fileName){
        int lastIndex = fileName.lastIndexOf('.');

        return  fileName.substring(lastIndex+1,fileName.length());
    }

    /***
     * 判断此文件夹是否存在 不存在就加入数组中
     * @param path
     * @param paths
     */
    public void getFolder(String path,List<String> paths){

        int index = path.indexOf("/");
        String folderName = path.substring(0, index);
        if (!paths.contains(folderName)){
            paths.add(folderName);
        }

    }

//    获取文件链接
    public String getUrl(String bucketName,String objectName) throws Exception{
        String objectUrl = minioClient.getObjectUrl(bucketName, objectName);
        return objectUrl;
    }
    
    public void copyObject(String bucketName,String objectName,String reName) throws Exception{
        minioClient.copyObject(bucketName, objectName, bucketName,reName);


    }

    public static void main(String[] args) throws Exception {

        MinioUtils minioUtils = new MinioUtils();
        try {
            // 检查'mybucket'是否存在。
            boolean found = minioClient.bucketExists("qq123456");
            if (found) {
                // 列出'mybucket'中所有未完成的multipart上传的的对象。
                Iterable<Result<Upload>> myObjects = minioClient.listIncompleteUploads("qq123456");
                for (Result<Upload> result : myObjects) {
                    Upload upload = result.get();
                    System.out.println(upload.uploadId() + ", " + upload.objectName());
                }

            } else {
                System.out.println("mybucket does not exist");
            }
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
        }


    }


}
